package com.hb.anative

import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

/**
 * 一行代码搞定Android6.0的权限申请
 *
 *在Android API 23以上的操作系统上进行权限申请的步骤虽然简单，但是如果要在每一处使用权限的地方进行申请就很麻烦了。
 *这里就分享一种利用Kotlin的扩展机制实现的一行代码搞定权限申请的实现，这里仅用读取GPS的例子来简要说明实现，对于其他权限申请，其实现过程是相同的。
 *
 *locationPermission { granted: Boolean ->
 *     enableLocation(granted)
 *}
 *
 * 精简后可以写成
 * locationPermission { enableLocation(it) }
 *
 *
 * 新的权限分为两类
 * Normal Permissions(普通权限) 一般不涉及用户隐私，是不需要用户进行授权
 * Dangerous Permission(高危权限)   涉及到用户隐私的，需要用户进行授权，比如读取sdcard、访问通讯录
 *      目前的高危权限是以组为单位进行管理的
 * 对于新权限的使用，我们需要关注的API有
 * ContextCompat.checkSelfPermission：检查权限
 * ActivityCompat.requestPermissions：申请权限
 * onRequestPermissionsResult：申请权限回调
 * ActivityCompat.shouldShowRequestPermissionRationale：被拒绝后向用户说明为什么使用此权限
 *
 */
private var permissionCode = 0

data class _Permission(val granted: (Boolean) -> Unit)

object PermissionManager {
    val permissionList = HashMap<Int, _Permission>()
    fun onRequestPermissionsResult(activity: Activity, requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        if (permissionList.containsKey(requestCode)) {
            val granted = permissionList.remove(requestCode) ?: return
            val isTip = ActivityCompat.shouldShowRequestPermissionRationale(activity, permissions[0])
            val isDenied = grantResults.isNotEmpty() && grantResults[0] != PackageManager.PERMISSION_GRANTED
            if (isDenied) {
                if (isTip) {
                    val code = ++permissionCode
                    permissionList[requestCode] = granted
                    ActivityCompat.requestPermissions(activity, permissions, code)
                } else {
                    granted.granted.invoke(false)
                }
            } else
                granted.granted.invoke(true)
        }
    }
}

fun Activity.locationPermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.LOCATION) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION), requestCode)
    }
}

fun Activity.storagePermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.STORAGE) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE), requestCode)
    }
}

fun Activity.contactsPermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.CONTACTS) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.READ_CONTACTS,
            Manifest.permission.GET_ACCOUNTS,
            Manifest.permission.WRITE_CONTACTS), requestCode)
    }
}

fun Activity.phonePermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.PHONE) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.READ_CALL_LOG,
            Manifest.permission.READ_PHONE_STATE,
            Manifest.permission.CALL_PHONE,
            Manifest.permission.WRITE_CALL_LOG,
            Manifest.permission.USE_SIP,
            Manifest.permission.PROCESS_OUTGOING_CALLS,
            Manifest.permission.ADD_VOICEMAIL), requestCode)
    }
}

fun Activity.calendarPermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.CALENDAR) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.READ_CALENDAR,
            Manifest.permission.WRITE_CALENDAR), requestCode)
    }
}

fun Activity.cameraPermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.CAMERA) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.CAMERA), requestCode)
    }
}

fun Activity.sensorsPermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.SENSORS) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.BODY_SENSORS), requestCode)
    }
}

fun Activity.microphonePermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.MICROPHONE) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.RECORD_AUDIO), requestCode)
    }
}

fun Activity.smsPermission(granted: (Boolean) -> Unit) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.SMS) == PackageManager.PERMISSION_GRANTED)
        granted(true)
    else {
        val requestCode = ++permissionCode
        PermissionManager.permissionList[requestCode] = _Permission(granted)
        ActivityCompat.requestPermissions(this, arrayOf(
            Manifest.permission.READ_SMS,
            Manifest.permission.RECEIVE_WAP_PUSH,
            Manifest.permission.RECEIVE_MMS,
            Manifest.permission.RECEIVE_SMS,
            Manifest.permission.SEND_SMS), requestCode)
    }
}
